/*
 * GrantRequestView.java
 *
 * Created on October 28, 2008, 10:51 AM
 */

package researchgrants.parts.GrantRequest;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.FlowLayout;
import java.awt.GridLayout;
import java.awt.Window;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.util.Iterator;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.JButton;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import researchgrants.parts.GrantRequest.agency.LoggedDataPanelsAgencyContact;
import researchgrants.parts.GrantRequest.statusChanges.GrantRequestStatusChange;
import researchgrants.parts.GrantRequest.statusChanges.GrantRequestStatusChangeAwarded;
import researchgrants.parts.GrantRequest.statusChanges.GrantRequestStatusChangeAwardedView;
import researchgrants.parts.GrantRequest.statusChanges.GrantRequestStatusChangeCancelled;
import researchgrants.parts.GrantRequest.statusChanges.GrantRequestStatusChangeCancelledView;
import researchgrants.parts.GrantRequest.statusChanges.GrantRequestStatusChangeCompleted;
import researchgrants.parts.GrantRequest.statusChanges.GrantRequestStatusChangeCompletedView;
import researchgrants.parts.GrantRequest.statusChanges.GrantRequestStatusChangeRejected;
import researchgrants.parts.GrantRequest.statusChanges.GrantRequestStatusChangeRejectedView;
import researchgrants.parts.GrantRequest.statusChanges.GrantRequestStatusChangeSubmitted;
import researchgrants.parts.GrantRequest.statusChanges.GrantRequestStatusChangeSubmittedView;
import researchgrants.parts.GrantRequest.statusChanges.GrantRequestStatusChangeView;
import researchgrants.parts.LoggedData.LoggedData;
import researchgrants.parts.LoggedData.panels.LoggedDataPanelsDate;
import researchgrants.parts.LoggedData.panels.LoggedDataPanelsText;
import researchgrants.parts.LoggedData.panels.LoggedDataPanelsTextArea;
import researchgrants.parts.GrantRequest.expensePurpose.LoggedDataPanelsListExpensePurpose;
import researchgrants.parts.GrantRequest.grantOfficer.LoggedDataPanelsListGrantOfficer;
import researchgrants.parts.GrantRequest.nsfcode.LoggedDataPanelsTreeNsfCode;
import researchgrants.parts.db.Db;
import researchgrants.parts.GrantRequest.perennialStipends.PanelsPerennialStipends;
import researchgrants.parts.GrantRequest.perennialStipends.PerennialStipends;
import researchgrants.parts.GrantRequest.reminder.PanelsReminder;
import researchgrants.parts.GrantRequest.reminder.Reminder;
import researchgrants.parts.GrantRequest.reminder.ReminderView;
import researchgrants.parts.panelsManager.CompoundDataPanelsManager;
import researchgrants.parts.panelsManager.LoggedDataPanelsManager;
import researchgrants.parts.pi.LoggedDataPanelsPis;
import researchgrants.utils.MyDialog;

/**
 * A class for displaying a GrantRequest
 * Since it it coupled with GrantRequest, it accesses its package methods for display
 * But because this class only deals with display, it is seperated.
 * 
 * The class support the display of an existing GrantRequest or the input of a new GrantRequest, depending on which constructor is called
 * @author  ohad
 */
public class GrantRequestView extends MyDialog {

    private static final String NewSectionHeader="New ";
    
    private static final int hgap=5;
    
    // the grant request to show or input.
    // if new, the field is null. But once saved a new grant request, this field is populated.
    private GrantRequest grantRequest;
    // if the view is for adding or editing
    private boolean isNewGrantRequest;
    
    // Creates an unbounded grant request view - for creating a new grant request
    GrantRequestView(Window parent) {
        super(parent);
        isNewGrantRequest=true;
        initComponents();
        initDisplay();
    }
    
    // Creates a bounded grant request view - for viewing and editing a grant request
    GrantRequestView(Window parent, GrantRequest grantRequest) {
        super(parent);
        this.grantRequest=grantRequest;
        isNewGrantRequest=false;
        initComponents();
        initDisplay();
    }

    // retreive the shown grant request
    // used for retreiving a newly created grant request.
    GrantRequest getGrantRequest() {
        return(grantRequest);
    }

    /** This method is called from within the constructor to
     * initialize the form.
     * WARNING: Do NOT modify this code. The content of this method is
     * always regenerated by the Form Editor.
     */
    @SuppressWarnings("unchecked")
    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
    private void initComponents() {
        java.awt.GridBagConstraints gridBagConstraints;

        pnlTopHeader = new javax.swing.JPanel();
        pnlID = new javax.swing.JPanel();
        lblCaptionId = new javax.swing.JLabel();
        lblId = new javax.swing.JLabel();
        pnlReminder = new javax.swing.JPanel();
        pnlReminder2 = new javax.swing.JPanel();
        lblCaptionReminder = new javax.swing.JLabel();
        pnlFieldReminder = new javax.swing.JPanel();
        pnlDeadline = new javax.swing.JPanel();
        lblCaptionDeadline = new javax.swing.JLabel();
        pnlFieldDeadline = new javax.swing.JPanel();
        pnlTitle = new javax.swing.JPanel();
        lblCaptionTitle = new javax.swing.JLabel();
        pnlFieldTitle = new javax.swing.JPanel();
        pnlFirstContact = new javax.swing.JPanel();
        lblCaptionFirstContact = new javax.swing.JLabel();
        pnlFieldFirstContact = new javax.swing.JPanel();
        pnlPis = new javax.swing.JPanel();
        pnlPis2 = new javax.swing.JPanel();
        lblCaptionPis = new javax.swing.JLabel();
        pnlFieldPis = new javax.swing.JPanel();
        pnlAgencyContact = new javax.swing.JPanel();
        pnlAgencyContact2 = new javax.swing.JPanel();
        lblCaptionAgencyContact = new javax.swing.JLabel();
        pnlFieldAgencyContact = new javax.swing.JPanel();
        pnlExpensePurpose = new javax.swing.JPanel();
        lblCaptionExpensePurpose = new javax.swing.JLabel();
        pnlFieldExpensePurpose = new javax.swing.JPanel();
        pnlNsfCode = new javax.swing.JPanel();
        pnlNsfCode2 = new javax.swing.JPanel();
        lblCaptionNsfCode = new javax.swing.JLabel();
        pnlFieldNsfCode = new javax.swing.JPanel();
        pnlGrantOfficer = new javax.swing.JPanel();
        lblCaptionGrantOfficer = new javax.swing.JLabel();
        pnlFieldGrantOfficer = new javax.swing.JPanel();
        pnlExpectedStipends = new javax.swing.JPanel();
        pnlExpectedStipends2 = new javax.swing.JPanel();
        lblCaptionExpectedStipends = new javax.swing.JLabel();
        pnlFieldExpectedStipends = new javax.swing.JPanel();
        pnlNotes = new javax.swing.JPanel();
        pnlNotes2 = new javax.swing.JPanel();
        lblCaptionNotes = new javax.swing.JLabel();
        pnlFieldNotes = new javax.swing.JPanel();
        pnlStatusChanges = new javax.swing.JPanel();
        pnlOptionalButtons = new javax.swing.JPanel();

        setDefaultCloseOperation(javax.swing.WindowConstants.DISPOSE_ON_CLOSE);
        org.jdesktop.application.ResourceMap resourceMap = org.jdesktop.application.Application.getInstance(researchgrants.ResearchGrantsApp.class).getContext().getResourceMap(GrantRequestView.class);
        setTitle(resourceMap.getString("Form.title")); // NOI18N
        setName("Form"); // NOI18N
        getContentPane().setLayout(new javax.swing.BoxLayout(getContentPane(), javax.swing.BoxLayout.PAGE_AXIS));

        pnlTopHeader.setName("pnlTopHeader"); // NOI18N
        pnlTopHeader.setLayout(new java.awt.BorderLayout());

        pnlID.setName("pnlID"); // NOI18N
        pnlID.setLayout(new java.awt.FlowLayout(java.awt.FlowLayout.LEFT, hgap, 0));

        lblCaptionId.setText(resourceMap.getString("lblCaptionId.text")); // NOI18N
        lblCaptionId.setName("lblCaptionId"); // NOI18N
        pnlID.add(lblCaptionId);

        lblId.setText(resourceMap.getString("lblId.text")); // NOI18N
        lblId.setName("lblId"); // NOI18N
        pnlID.add(lblId);

        pnlTopHeader.add(pnlID, java.awt.BorderLayout.WEST);

        pnlReminder.setName("pnlReminder"); // NOI18N
        pnlReminder.setLayout(new java.awt.FlowLayout(java.awt.FlowLayout.LEFT, hgap
            , 0));

    pnlReminder2.setName("pnlReminder2"); // NOI18N
    pnlReminder2.setLayout(new java.awt.GridBagLayout());

    lblCaptionReminder.setText(resourceMap.getString("lblCaptionReminder.text")); // NOI18N
    lblCaptionReminder.setVerticalAlignment(javax.swing.SwingConstants.TOP);
    lblCaptionReminder.setAlignmentY(1.0F);
    lblCaptionReminder.setName("lblCaptionReminder"); // NOI18N
    lblCaptionReminder.setVerticalTextPosition(javax.swing.SwingConstants.TOP);
    gridBagConstraints = new java.awt.GridBagConstraints();
    gridBagConstraints.gridwidth = java.awt.GridBagConstraints.RELATIVE;
    gridBagConstraints.gridheight = java.awt.GridBagConstraints.RELATIVE;
    gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
    gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHEAST;
    pnlReminder2.add(lblCaptionReminder, gridBagConstraints);

    pnlFieldReminder.setName("pnlFieldReminder"); // NOI18N
    pnlFieldReminder.setLayout(new java.awt.FlowLayout(java.awt.FlowLayout.LEFT, 0, 0));
    gridBagConstraints = new java.awt.GridBagConstraints();
    gridBagConstraints.gridwidth = java.awt.GridBagConstraints.REMAINDER;
    gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
    gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTH;
    pnlReminder2.add(pnlFieldReminder, gridBagConstraints);

    pnlReminder.add(pnlReminder2);

    pnlTopHeader.add(pnlReminder, java.awt.BorderLayout.EAST);

    getContentPane().add(pnlTopHeader);

    pnlDeadline.setName("pnlDeadline"); // NOI18N
    pnlDeadline.setLayout(new java.awt.FlowLayout(java.awt.FlowLayout.LEFT, hgap, 0));

    lblCaptionDeadline.setText(resourceMap.getString("lblCaptionDeadline.text")); // NOI18N
    lblCaptionDeadline.setName("lblCaptionDeadline"); // NOI18N
    pnlDeadline.add(lblCaptionDeadline);

    pnlFieldDeadline.setName("pnlFieldDeadline"); // NOI18N
    pnlFieldDeadline.setLayout(new java.awt.FlowLayout(java.awt.FlowLayout.LEFT, 0, 0));
    pnlDeadline.add(pnlFieldDeadline);

    getContentPane().add(pnlDeadline);

    pnlTitle.setName("pnlTitle"); // NOI18N
    pnlTitle.setLayout(new java.awt.FlowLayout(java.awt.FlowLayout.LEFT, hgap, 0));

    lblCaptionTitle.setText(resourceMap.getString("lblCaptionTitle.text")); // NOI18N
    lblCaptionTitle.setName("lblCaptionTitle"); // NOI18N
    pnlTitle.add(lblCaptionTitle);

    pnlFieldTitle.setName("pnlFieldTitle"); // NOI18N
    pnlFieldTitle.setLayout(new java.awt.FlowLayout(java.awt.FlowLayout.LEFT, 0, 0));
    pnlTitle.add(pnlFieldTitle);

    getContentPane().add(pnlTitle);

    pnlFirstContact.setName("pnlFirstContact"); // NOI18N
    pnlFirstContact.setLayout(new java.awt.FlowLayout(java.awt.FlowLayout.LEFT, hgap, 0));

    lblCaptionFirstContact.setText(resourceMap.getString("lblCaptionFirstContact.text")); // NOI18N
    lblCaptionFirstContact.setName("lblCaptionFirstContact"); // NOI18N
    pnlFirstContact.add(lblCaptionFirstContact);

    pnlFieldFirstContact.setName("pnlFieldFirstContact"); // NOI18N
    pnlFieldFirstContact.setLayout(new java.awt.FlowLayout(java.awt.FlowLayout.LEFT, 0, 0));
    pnlFirstContact.add(pnlFieldFirstContact);

    getContentPane().add(pnlFirstContact);

    pnlPis.setName("pnlPis"); // NOI18N
    pnlPis.setLayout(new java.awt.FlowLayout(java.awt.FlowLayout.LEFT, hgap, 0));

    pnlPis2.setName("pnlPis2"); // NOI18N
    pnlPis2.setLayout(new java.awt.GridBagLayout());

    lblCaptionPis.setText(resourceMap.getString("lblCaptionPis.text")); // NOI18N
    lblCaptionPis.setVerticalAlignment(javax.swing.SwingConstants.TOP);
    lblCaptionPis.setName("lblCaptionPis"); // NOI18N
    lblCaptionPis.setVerticalTextPosition(javax.swing.SwingConstants.TOP);
    gridBagConstraints = new java.awt.GridBagConstraints();
    gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHEAST;
    pnlPis2.add(lblCaptionPis, gridBagConstraints);

    pnlFieldPis.setName("pnlFieldPis"); // NOI18N
    pnlFieldPis.setLayout(new java.awt.FlowLayout(java.awt.FlowLayout.LEFT, 0, 0));
    pnlPis2.add(pnlFieldPis, new java.awt.GridBagConstraints());

    pnlPis.add(pnlPis2);

    getContentPane().add(pnlPis);

    pnlAgencyContact.setName("pnlAgencyContact"); // NOI18N
    pnlAgencyContact.setLayout(new java.awt.FlowLayout(java.awt.FlowLayout.LEFT, hgap, 0));

    pnlAgencyContact2.setName("pnlAgencyContact2"); // NOI18N
    pnlAgencyContact2.setLayout(new java.awt.GridBagLayout());

    lblCaptionAgencyContact.setText(resourceMap.getString("lblCaptionAgencyContact.text")); // NOI18N
    lblCaptionAgencyContact.setVerticalAlignment(javax.swing.SwingConstants.TOP);
    lblCaptionAgencyContact.setName("lblCaptionAgencyContact"); // NOI18N
    lblCaptionAgencyContact.setVerticalTextPosition(javax.swing.SwingConstants.TOP);
    gridBagConstraints = new java.awt.GridBagConstraints();
    gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHEAST;
    pnlAgencyContact2.add(lblCaptionAgencyContact, gridBagConstraints);

    pnlFieldAgencyContact.setName("pnlFieldAgencyContact"); // NOI18N
    pnlFieldAgencyContact.setLayout(new java.awt.FlowLayout(java.awt.FlowLayout.LEFT, 0, 0));
    pnlAgencyContact2.add(pnlFieldAgencyContact, new java.awt.GridBagConstraints());

    pnlAgencyContact.add(pnlAgencyContact2);

    getContentPane().add(pnlAgencyContact);

    pnlExpensePurpose.setName("pnlExpensePurpose"); // NOI18N
    pnlExpensePurpose.setLayout(new java.awt.FlowLayout(java.awt.FlowLayout.LEFT, hgap, 0));

    lblCaptionExpensePurpose.setText(resourceMap.getString("lblCaptionExpensePurpose.text")); // NOI18N
    lblCaptionExpensePurpose.setVerticalAlignment(javax.swing.SwingConstants.TOP);
    lblCaptionExpensePurpose.setName("lblCaptionExpensePurpose"); // NOI18N
    lblCaptionExpensePurpose.setVerticalTextPosition(javax.swing.SwingConstants.TOP);
    pnlExpensePurpose.add(lblCaptionExpensePurpose);

    pnlFieldExpensePurpose.setName("pnlFieldExpensePurpose"); // NOI18N
    pnlFieldExpensePurpose.setLayout(new java.awt.FlowLayout(java.awt.FlowLayout.LEFT, 0, 0));
    pnlExpensePurpose.add(pnlFieldExpensePurpose);

    getContentPane().add(pnlExpensePurpose);

    pnlNsfCode.setName("pnlNsfCode"); // NOI18N
    pnlNsfCode.setLayout(new java.awt.FlowLayout(java.awt.FlowLayout.LEFT, hgap, 0));

    pnlNsfCode2.setName("pnlNsfCode2"); // NOI18N
    pnlNsfCode2.setLayout(new java.awt.GridBagLayout());

    lblCaptionNsfCode.setText(resourceMap.getString("lblCaptionNsfCode.text")); // NOI18N
    lblCaptionNsfCode.setVerticalAlignment(javax.swing.SwingConstants.TOP);
    lblCaptionNsfCode.setName("lblCaptionNsfCode"); // NOI18N
    lblCaptionNsfCode.setVerticalTextPosition(javax.swing.SwingConstants.TOP);
    gridBagConstraints = new java.awt.GridBagConstraints();
    gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
    pnlNsfCode2.add(lblCaptionNsfCode, gridBagConstraints);

    pnlFieldNsfCode.setName("pnlFieldNsfCode"); // NOI18N
    pnlFieldNsfCode.setLayout(new java.awt.FlowLayout(java.awt.FlowLayout.LEFT, 0, 0));
    gridBagConstraints = new java.awt.GridBagConstraints();
    gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTH;
    pnlNsfCode2.add(pnlFieldNsfCode, gridBagConstraints);

    pnlNsfCode.add(pnlNsfCode2);

    getContentPane().add(pnlNsfCode);

    pnlGrantOfficer.setName("pnlGrantOfficer"); // NOI18N
    pnlGrantOfficer.setLayout(new java.awt.FlowLayout(java.awt.FlowLayout.LEFT, hgap, 0));

    lblCaptionGrantOfficer.setText(resourceMap.getString("lblCaptionGrantOfficer.text")); // NOI18N
    lblCaptionGrantOfficer.setVerticalAlignment(javax.swing.SwingConstants.TOP);
    lblCaptionGrantOfficer.setName("lblCaptionGrantOfficer"); // NOI18N
    lblCaptionGrantOfficer.setVerticalTextPosition(javax.swing.SwingConstants.TOP);
    pnlGrantOfficer.add(lblCaptionGrantOfficer);

    pnlFieldGrantOfficer.setName("pnlFieldGrantOfficer"); // NOI18N
    pnlFieldGrantOfficer.setLayout(new java.awt.FlowLayout(java.awt.FlowLayout.LEFT, 0, 0));
    pnlGrantOfficer.add(pnlFieldGrantOfficer);

    getContentPane().add(pnlGrantOfficer);

    pnlExpectedStipends.setName("pnlExpectedStipends"); // NOI18N
    pnlExpectedStipends.setLayout(new java.awt.FlowLayout(java.awt.FlowLayout.LEFT, hgap
        , 0));

pnlExpectedStipends2.setName("pnlExpectedStipends2"); // NOI18N
pnlExpectedStipends2.setLayout(new java.awt.GridBagLayout());

lblCaptionExpectedStipends.setText(resourceMap.getString("lblCaptionExpectedStipends.text")); // NOI18N
lblCaptionExpectedStipends.setVerticalAlignment(javax.swing.SwingConstants.TOP);
lblCaptionExpectedStipends.setAlignmentY(1.0F);
lblCaptionExpectedStipends.setName("lblCaptionExpectedStipends"); // NOI18N
lblCaptionExpectedStipends.setVerticalTextPosition(javax.swing.SwingConstants.TOP);
gridBagConstraints = new java.awt.GridBagConstraints();
gridBagConstraints.gridwidth = java.awt.GridBagConstraints.RELATIVE;
gridBagConstraints.gridheight = java.awt.GridBagConstraints.RELATIVE;
gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHEAST;
pnlExpectedStipends2.add(lblCaptionExpectedStipends, gridBagConstraints);

pnlFieldExpectedStipends.setName("pnlFieldExpectedStipends"); // NOI18N
pnlFieldExpectedStipends.setLayout(new java.awt.FlowLayout(java.awt.FlowLayout.LEFT, 0, 0));
gridBagConstraints = new java.awt.GridBagConstraints();
gridBagConstraints.gridwidth = java.awt.GridBagConstraints.REMAINDER;
gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTH;
pnlExpectedStipends2.add(pnlFieldExpectedStipends, gridBagConstraints);

pnlExpectedStipends.add(pnlExpectedStipends2);

getContentPane().add(pnlExpectedStipends);

pnlNotes.setName("pnlNotes"); // NOI18N
pnlNotes.setLayout(new java.awt.FlowLayout(java.awt.FlowLayout.LEFT, hgap
    , 0));

    pnlNotes2.setName("pnlNotes2"); // NOI18N
    pnlNotes2.setLayout(new java.awt.GridBagLayout());

    lblCaptionNotes.setText(resourceMap.getString("lblCaptionNotes.text")); // NOI18N
    lblCaptionNotes.setVerticalAlignment(javax.swing.SwingConstants.TOP);
    lblCaptionNotes.setAlignmentY(1.0F);
    lblCaptionNotes.setName("lblCaptionNotes"); // NOI18N
    lblCaptionNotes.setVerticalTextPosition(javax.swing.SwingConstants.TOP);
    gridBagConstraints = new java.awt.GridBagConstraints();
    gridBagConstraints.gridwidth = java.awt.GridBagConstraints.RELATIVE;
    gridBagConstraints.gridheight = java.awt.GridBagConstraints.RELATIVE;
    gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
    gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHEAST;
    pnlNotes2.add(lblCaptionNotes, gridBagConstraints);

    pnlFieldNotes.setName("pnlFieldNotes"); // NOI18N
    pnlFieldNotes.setLayout(new java.awt.FlowLayout(java.awt.FlowLayout.LEFT, 0, 0));
    gridBagConstraints = new java.awt.GridBagConstraints();
    gridBagConstraints.gridwidth = java.awt.GridBagConstraints.REMAINDER;
    gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
    gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTH;
    pnlNotes2.add(pnlFieldNotes, gridBagConstraints);

    pnlNotes.add(pnlNotes2);

    getContentPane().add(pnlNotes);

    pnlStatusChanges.setName("pnlStatusChanges"); // NOI18N
    pnlStatusChanges.setLayout(new javax.swing.BoxLayout(pnlStatusChanges, javax.swing.BoxLayout.PAGE_AXIS));
    getContentPane().add(pnlStatusChanges);

    pnlOptionalButtons.setName("pnlOptionalButtons"); // NOI18N
    pnlOptionalButtons.setLayout(new javax.swing.BoxLayout(pnlOptionalButtons, javax.swing.BoxLayout.LINE_AXIS));
    getContentPane().add(pnlOptionalButtons);

    pack();
    }// </editor-fold>//GEN-END:initComponents


    // Variables declaration - do not modify//GEN-BEGIN:variables
    private javax.swing.JLabel lblCaptionAgencyContact;
    private javax.swing.JLabel lblCaptionDeadline;
    private javax.swing.JLabel lblCaptionExpectedStipends;
    private javax.swing.JLabel lblCaptionExpensePurpose;
    private javax.swing.JLabel lblCaptionFirstContact;
    private javax.swing.JLabel lblCaptionGrantOfficer;
    private javax.swing.JLabel lblCaptionId;
    private javax.swing.JLabel lblCaptionNotes;
    private javax.swing.JLabel lblCaptionNsfCode;
    private javax.swing.JLabel lblCaptionPis;
    private javax.swing.JLabel lblCaptionReminder;
    private javax.swing.JLabel lblCaptionTitle;
    private javax.swing.JLabel lblId;
    private javax.swing.JPanel pnlAgencyContact;
    private javax.swing.JPanel pnlAgencyContact2;
    private javax.swing.JPanel pnlDeadline;
    private javax.swing.JPanel pnlExpectedStipends;
    private javax.swing.JPanel pnlExpectedStipends2;
    private javax.swing.JPanel pnlExpensePurpose;
    private javax.swing.JPanel pnlFieldAgencyContact;
    private javax.swing.JPanel pnlFieldDeadline;
    private javax.swing.JPanel pnlFieldExpectedStipends;
    private javax.swing.JPanel pnlFieldExpensePurpose;
    private javax.swing.JPanel pnlFieldFirstContact;
    private javax.swing.JPanel pnlFieldGrantOfficer;
    private javax.swing.JPanel pnlFieldNotes;
    private javax.swing.JPanel pnlFieldNsfCode;
    private javax.swing.JPanel pnlFieldPis;
    private javax.swing.JPanel pnlFieldReminder;
    private javax.swing.JPanel pnlFieldTitle;
    private javax.swing.JPanel pnlFirstContact;
    private javax.swing.JPanel pnlGrantOfficer;
    private javax.swing.JPanel pnlID;
    private javax.swing.JPanel pnlNotes;
    private javax.swing.JPanel pnlNotes2;
    private javax.swing.JPanel pnlNsfCode;
    private javax.swing.JPanel pnlNsfCode2;
    private javax.swing.JPanel pnlOptionalButtons;
    private javax.swing.JPanel pnlPis;
    private javax.swing.JPanel pnlPis2;
    private javax.swing.JPanel pnlReminder;
    private javax.swing.JPanel pnlReminder2;
    private javax.swing.JPanel pnlStatusChanges;
    private javax.swing.JPanel pnlTitle;
    private javax.swing.JPanel pnlTopHeader;
    // End of variables declaration//GEN-END:variables

    /////////////////////////////
    // all the internal values
    /////////////////////////////
    private LoggedDataPanelsManager titleView;
    private LoggedDataPanelsManager deadlineView;
    private LoggedDataPanelsManager firstContactView;
    private LoggedDataPanelsManager pisView;
    private LoggedDataPanelsManager expensePurposeView;
    private LoggedDataPanelsManager nsfCodeView;
    private LoggedDataPanelsManager grantOfficerView;
    private LoggedDataPanelsManager notesView;
    private LoggedDataPanelsManager agencyContactView;
    private CompoundDataPanelsManager expectedPerennialStipendsView;
    private CompoundDataPanelsManager reminderView;
    
    // a global interaction fields
    private JButton btnSaveAll;
    private JPanel pnlWarnings=new JPanel();

    // redisplays the content.
    // used on initialization and future refresh of top-level data, excluding specific fields (as they maintain their state).
    private void initDisplay() {
        // must init the button so it will be enabled or disabled by the other fields
        if (isNewGrantRequest) {
            btnSaveAll=new JButton("Save New Grant Request");
            btnSaveAll.addActionListener(new ActionListener() {

                public void actionPerformed(ActionEvent e) {
                    createNewGrantRequestFromFields();
                }
            });
        }

        if (isNewGrantRequest) {
            lblId.setText("<Auto>");
        } else {
            lblId.setText(Integer.toString(grantRequest.getId()));
        }

        ///////////////////////////////////////
        // adds all the internal data's views
        ///////////////////////////////////////
        
        {
            LoggedData title=null, deadline=null, firstContact=null, pis=null, agencyContact=null, expensePurpose=null, nsfCode=null, grantOfficer=null, notes=null;
            PerennialStipends expectedPerennialStipends=null;
            Reminder reminder=null;
            if (!isNewGrantRequest) {
                title=grantRequest.getLoggedDataTitle();
                deadline=grantRequest.getLoggedDataDeadline();
                firstContact=grantRequest.getLoggedDataFirstContact();
                pis=grantRequest.getLoggedDataPis();
                agencyContact=grantRequest.getLoggedDataAgencyContact();
                expensePurpose=grantRequest.getLoggedDataExpensePurpose();
                nsfCode=grantRequest.getLoggedDataNsfCode();
                grantOfficer=grantRequest.getLoggedDataGrantOfficer();
                notes=grantRequest.getLoggedDataNotes();
                expectedPerennialStipends=grantRequest.getExpectedPerennialStipends();
                reminder=grantRequest.getCurrentReminder();
                
            }
            titleView=createLoggedDataPanelManager(false, isNewGrantRequest, new LoggedDataPanelsText(),this, title, pnlFieldTitle);
            deadlineView=createLoggedDataPanelManager(false, isNewGrantRequest, new LoggedDataPanelsDate(),this, deadline, pnlFieldDeadline);
            firstContactView=createLoggedDataPanelManager(false, isNewGrantRequest, new LoggedDataPanelsDate(),this, firstContact, pnlFieldFirstContact);
            {
                LoggedDataPanelsPis panels=new LoggedDataPanelsPis();
                ChangeListener changeEventListener = new PiChangeListener(panels);
                pisView=createLoggedDataPanelManager(true, isNewGrantRequest, panels, this, pis, pnlFieldPis, changeEventListener);
            }
            {
                LoggedDataPanelsAgencyContact panels=new LoggedDataPanelsAgencyContact();
                ChangeListener changeEventListener = new AgencyContactChangeListener(panels);
                agencyContactView=createLoggedDataPanelManager(false, isNewGrantRequest, panels,this, agencyContact, pnlFieldAgencyContact, changeEventListener);
            }
            expensePurposeView=createLoggedDataPanelManager(false, isNewGrantRequest, new LoggedDataPanelsListExpensePurpose(),this, expensePurpose, pnlFieldExpensePurpose);
            {
                LoggedDataPanelsTreeNsfCode panels=new LoggedDataPanelsTreeNsfCode();
                ChangeListener changeEventListener = new NsfCodeChangeListener(panels);
                nsfCodeView=createLoggedDataPanelManager(false, isNewGrantRequest, panels,this, nsfCode, pnlFieldNsfCode, changeEventListener);
            }
            {
                LoggedDataPanelsListGrantOfficer panels=new LoggedDataPanelsListGrantOfficer();
                ChangeListener changeEventListener = new GrantOfficerChangeListener(panels);
                grantOfficerView=createLoggedDataPanelManager(true, isNewGrantRequest, panels,this, grantOfficer, pnlFieldGrantOfficer, changeEventListener);
            }
         
            {
                expectedPerennialStipendsView=new CompoundDataPanelsManager();
                expectedPerennialStipendsView.setMandatory(false);
                expectedPerennialStipendsView.startAsNew(isNewGrantRequest);
                {
                    PanelsPerennialStipends panelsPerennialStipends=new PanelsPerennialStipends();
                    if (!isNewGrantRequest) {
                        panelsPerennialStipends.setData(expectedPerennialStipends);
                    }
                    ChangeListener changeEventListener = new PerennialStipendsChangeListener(panelsPerennialStipends);
                    panelsPerennialStipends.addChangeListener(changeEventListener);
                    panelsPerennialStipends.setParent(this, pnlFieldExpectedStipends);
                    expectedPerennialStipendsView.setPanels(panelsPerennialStipends);
                }
                pnlFieldExpectedStipends.removeAll();
                pnlFieldExpectedStipends.add(expectedPerennialStipendsView);
                expectedPerennialStipendsView.display();
            }
                    
            notesView=createLoggedDataPanelManager(false, isNewGrantRequest, new LoggedDataPanelsTextArea(),this, notes, pnlFieldNotes);

        
            {
                reminderView=new CompoundDataPanelsManager();
                reminderView.setMandatory(false);
//                expectedPerennialStipendsView.startAsNew(isNewGrantRequest);
                {
                    PanelsReminder panelsReminder=new PanelsReminder();
                    if (!isNewGrantRequest) {
                        panelsReminder.setData(reminder);
                    }
                    panelsReminder.setMandatoryData(grantRequest);
                    panelsReminder.setParent(this, pnlFieldReminder);
                    reminderView.setPanels(panelsReminder);
                }
                pnlFieldReminder.removeAll();
                pnlFieldReminder.add(reminderView);
                reminderView.display();
            }
        
        }
        
        
        
        /////////////////////////////////
        // adds all the status changes
        /////////////////////////////////

        pnlStatusChanges.removeAll();
        GrantRequestStatusChange lastStatusChange=null;
        if (!isNewGrantRequest) {
            for (Iterator<GrantRequestStatusChange> it = grantRequest.statusChangeList.iterator(); it.hasNext();) {
                GrantRequestStatusChange grantRequestStatusChange = it.next();
                GrantRequestStatusChangeView newView = grantRequestStatusChange.getView(this);
                if (it.hasNext()) {
                    pnlStatusChanges.add(wrapSection(newView, grantRequestStatusChange.getStatusChangeTitle()));
                } else {
                    pnlStatusChanges.add(wrapLastStatusChangeSection(newView, grantRequestStatusChange.getStatusChangeTitle(), grantRequestStatusChange));
                }
                lastStatusChange=grantRequestStatusChange;
            }
        }

        
        //////////////////////////////////////
        /// Deals with the buttons
        //////////////////////////////////////
        
        JPanel pnlOptionalButtonsInner=new JPanel(new FlowLayout(FlowLayout.CENTER, 0, 0));
        pnlOptionalButtonsInner.setLayout(new GridLayout());
        
        boolean displayButtonsPanel=false;
        if (isNewGrantRequest) {
            // if the grant is new, only allow to save the initial data
            JPanel pnlOptionalButtonsInner2=new JPanel(new BorderLayout(0, 0));
            pnlOptionalButtonsInner2.add(pnlWarnings, BorderLayout.NORTH);
            pnlOptionalButtonsInner2.add(btnSaveAll, BorderLayout.CENTER);
            pnlOptionalButtonsInner.add(pnlOptionalButtonsInner2);
            displayButtonsPanel=true;
        } else {
            // if the grant is already exists, allow to make transition to its status
            // each status has its own buttons
            // so, the logic of adding a status change is maintained here
            if (lastStatusChange==null) {
                // initial grant request
                JButton btnCancel=new JButton("Cancel Grant Request");
                btnCancel.addActionListener(new ActionListenerCancelGrantRequestButton(this));
                pnlOptionalButtonsInner.add(wrapButton(btnCancel));
                JButton btnSubmit=new JButton("Submit Grant Request");
                btnSubmit.addActionListener(new ActionListenerSubmitGrantRequestButton(this));
                pnlOptionalButtonsInner.add(wrapButton(btnSubmit));
                displayButtonsPanel=true;
            } else {
                if (lastStatusChange instanceof GrantRequestStatusChangeCancelled) {
                   // cancelled grant request - no buttons
                }
                else {
                    if (lastStatusChange instanceof GrantRequestStatusChangeSubmitted) {
                        // submitted grant request
                        JButton btnReject=new JButton("Grant Request Rejected");
                        btnReject.addActionListener(new ActionListenerRejectGrantRequestButton(this));
                        pnlOptionalButtonsInner.add(wrapButton(btnReject));
                        JButton btnAward=new JButton("Grant Awarded");
                        btnAward.addActionListener(new ActionListenerAwardGrantRequestButton(this));
                        pnlOptionalButtonsInner.add(wrapButton(btnAward));
                        displayButtonsPanel=true;
                    } else {
                        if (lastStatusChange instanceof GrantRequestStatusChangeRejected) {
                            // rejected grant request - no buttons
                        } else {
                            if (lastStatusChange instanceof GrantRequestStatusChangeAwarded) {
                                // submitted grant request
                                JButton btnCompleted=new JButton("Grant Request Completed");
                                btnCompleted.addActionListener(new ActionListenerCompleteGrantRequestButton(this));
                                pnlOptionalButtonsInner.add(wrapButton(btnCompleted));
                                displayButtonsPanel=true;
                            } else {

                            }
                            
                        }

                    }
                    
                }
            }
        }
        
        pnlOptionalButtons.removeAll();
        // if no buttons, remove panel
        if (displayButtonsPanel) {
                pnlOptionalButtons.add(wrapSection(pnlOptionalButtonsInner, "Options"));
        }
        
        validateEntireForm();
        pack();
        setLocationRelativeTo(getParent());
        setVisible(true);
    }

    // wraps a button with a panel, located in the center
    private JPanel wrapButton(JButton btn) {
        JPanel wrapPanel=new JPanel(new FlowLayout(FlowLayout.CENTER, 0, 0));
        wrapPanel.add(btn);
        return(wrapPanel);
    }
    
    // wraps specifically the last status change section - creates the erase button for it
    private JPanel wrapLastStatusChangeSection(JPanel sectionPanel, String title, GrantRequestStatusChange grantRequestStatusChange) {
        JPanel pnlContent=new JPanel(new BorderLayout(0, 0));

        JPanel pnlButton=new JPanel(new BorderLayout(0, 0));
        JButton btnEraseLastStatusChange=new JButton("Erase This Status");
        btnEraseLastStatusChange.addActionListener(new btnEraseLastStatusChangeActionListener(this, title, grantRequestStatusChange));
        pnlButton.add(btnEraseLastStatusChange, BorderLayout.EAST);
        pnlContent.add(pnlButton, BorderLayout.NORTH);

        pnlContent.add(sectionPanel, BorderLayout.CENTER);
        return(wrapSection(pnlContent, title));
    }

    // saves a new grant request from the different fields
    // actually maintain the database and logic for creating a new grant request
    // only to be used if this view is for a new grant request.
    private void createNewGrantRequestFromFields() {
        try {

            Connection conn=Db.openDbConnection();
            PreparedStatement createGrantRequestStatement = Db.createPreparedStatement(conn, "INSERT INTO tblGrantRequests (TitleRef, PIsRef, FirstContactRef, DeadlineRef, ExpensePurposeRef, NsfCodeRef, GrantOfficerRef, NotesRef, AgencyContactRef, ExpectedPerennialStipendsID, ReminderRef) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)");

            
            ////////////////////////////////////
            // Save all different data pieces
            ////////////////////////////////////
            
            createGrantRequestStatement.setInt(1, saveLoggedDataPanelsManagerData(titleView));
            createGrantRequestStatement.setInt(2, saveLoggedDataPanelsManagerData(pisView));
            createGrantRequestStatement.setInt(3, saveLoggedDataPanelsManagerData(firstContactView));
            createGrantRequestStatement.setInt(4, saveLoggedDataPanelsManagerData(deadlineView));
            createGrantRequestStatement.setInt(5, saveLoggedDataPanelsManagerData(expensePurposeView));
            createGrantRequestStatement.setInt(6, saveLoggedDataPanelsManagerData(nsfCodeView));
            createGrantRequestStatement.setInt(7, saveLoggedDataPanelsManagerData(grantOfficerView));
            createGrantRequestStatement.setInt(8, saveLoggedDataPanelsManagerData(notesView));
            createGrantRequestStatement.setInt(9, saveLoggedDataPanelsManagerData(agencyContactView));

            ((PanelsPerennialStipends)expectedPerennialStipendsView.getPanels()).saveData();
            createGrantRequestStatement.setInt(10, ((PanelsPerennialStipends)expectedPerennialStipendsView.getPanels()).getPerennialStipends().getId());

            LoggedData newReminderLoggedData = LoggedData.createNew("");
            createGrantRequestStatement.setInt(11, newReminderLoggedData.getId());
            
                    
            /////////////////////////////////////////
            // Saves the GrantRequest itself
            /////////////////////////////////////////
            createGrantRequestStatement.executeUpdate();

            int newGrantRequestId = Db.getLastIdentity();
            createGrantRequestStatement.close();
            Db.closeDbConnection(conn);
            
            // saves the newly created grant request
            this.grantRequest=GrantRequest.getById(newGrantRequestId);
            
            //setVisible(false);
            
        } catch (SQLException ex) {
            Logger.getLogger(GrantRequestView.class.getName()).log(Level.SEVERE, null, ex);
        }
        
        // refreshes the display
        isNewGrantRequest=false;
        initDisplay();
                    
    }

    /////////////////////////
    // Validates the form
    /////////////////////////
    
    // each individual component is validated/invalidated seperately, using its designated Listener
    // the entire form is revalidated after any individual change
    
    private boolean isPiValid=false;
    private boolean isGrantOfficerValid=false;
    private boolean isAgencyContactValid=true;
    private boolean isNsfCodeValid=true;
    private boolean isExpectedPerennialStipendsValid=true;
    
    
    private void validateEntireForm() {
        setSaveEnabled(isPiValid && isGrantOfficerValid && isAgencyContactValid && isNsfCodeValid && isExpectedPerennialStipendsValid);
        pnlWarnings.removeAll();
        int warnings=0;
        if (!isPiValid) {
            JLabel lblWarning=new JLabel("You must select a PI");
            lblWarning.setForeground(Color.RED);
            pnlWarnings.add(lblWarning);
            warnings++;
        }
        if (!isGrantOfficerValid) {
            JLabel lblWarning=new JLabel("You must select a Grant Officer");
            lblWarning.setForeground(Color.RED);
            pnlWarnings.add(lblWarning);
            warnings++;
        }
        if (!isAgencyContactValid) {
            JLabel lblWarning=new JLabel("Agency contact is Invalid.");
            lblWarning.setForeground(Color.RED);
            pnlWarnings.add(lblWarning);
            warnings++;
        }
        if (!isNsfCodeValid) {
            JLabel lblWarning=new JLabel("Nsf code must be a ");
            lblWarning.setForeground(Color.RED);
            pnlWarnings.add(lblWarning);
            warnings++;
        }
        if (!isExpectedPerennialStipendsValid) {
            JLabel lblWarning=new JLabel("Expected Stipends is invalid");
            lblWarning.setForeground(Color.RED);
            pnlWarnings.add(lblWarning);
            warnings++;
        }
        

        pnlWarnings.setLayout(new GridLayout(warnings, 1));
        pnlWarnings.revalidate();
    }
    
    
    private class PerennialStipendsChangeListener implements ChangeListener {
        PanelsPerennialStipends panelsPerennialStipends;

        private PerennialStipendsChangeListener(PanelsPerennialStipends panelsPerennialStipends) {
            this.panelsPerennialStipends=panelsPerennialStipends;
        }

        public void stateChanged(ChangeEvent e) {
            isExpectedPerennialStipendsValid=panelsPerennialStipends.isValid();
            validateEntireForm();
        }
    }
            
    private class NsfCodeChangeListener implements ChangeListener {
        LoggedDataPanelsTreeNsfCode loggedDataPanels;

        public NsfCodeChangeListener(LoggedDataPanelsTreeNsfCode loggedDataPanels) {
            this.loggedDataPanels = loggedDataPanels;
        }

        public void stateChanged(ChangeEvent e) {
            isNsfCodeValid=(loggedDataPanels.isValid());
            validateEntireForm();
        }
    }

    private class PiChangeListener implements ChangeListener {
        LoggedDataPanelsPis loggedDataPanelsPis;

        public PiChangeListener(LoggedDataPanelsPis loggedDataPanelsPis) {
            this.loggedDataPanelsPis = loggedDataPanelsPis;
        }

        public void stateChanged(ChangeEvent e) {
            isPiValid=((loggedDataPanelsPis.isValid()) && (!loggedDataPanelsPis.isEmpty()));
            validateEntireForm();
        }
    }

    private class GrantOfficerChangeListener implements ChangeListener {
        LoggedDataPanelsListGrantOfficer loggedDataPanelsGrantOfficers;

        public GrantOfficerChangeListener(LoggedDataPanelsListGrantOfficer loggedDataPanelsPis) {
            this.loggedDataPanelsGrantOfficers = loggedDataPanelsPis;
        }

        public void stateChanged(ChangeEvent e) {
            isGrantOfficerValid=((loggedDataPanelsGrantOfficers.isValid()) && (!loggedDataPanelsGrantOfficers.isEmpty()));
            validateEntireForm();
        }
    }
    
    private class AgencyContactChangeListener implements ChangeListener {

        LoggedDataPanelsAgencyContact loggedDataPanelsAgencyContact;
        
        private AgencyContactChangeListener(LoggedDataPanelsAgencyContact loggedDataPanelsAgencyContact) {
            this.loggedDataPanelsAgencyContact=loggedDataPanelsAgencyContact;
        }

        public void stateChanged(ChangeEvent e) {
            isAgencyContactValid=loggedDataPanelsAgencyContact.isValid();
            validateEntireForm();
        }
    }
    
    private void setSaveEnabled(boolean enabled) {
        // will only be used when a global save button is availalbe
        if (btnSaveAll!=null) {
            btnSaveAll.setEnabled(enabled);
        }
    }


    //////////////////////////////
    // Buttons action listeners 
    //////////////////////////////
    
    private class ActionListenerSubmitGrantRequestButton implements ActionListener {
    
        private GrantRequestView grantRequestView;
        public ActionListenerSubmitGrantRequestButton(GrantRequestView grantRequestView) {
            this.grantRequestView=grantRequestView;
        }

        public void actionPerformed(ActionEvent e) {
            grantRequestView.pnlOptionalButtons.setVisible(false);
            
            GrantRequestStatusChangeSubmittedView inputNew = GrantRequestStatusChangeSubmitted.inputNew(grantRequestView, grantRequest, new ActionListenerNewStatusChangeSaved(grantRequestView), new ActionListenerNewStatusChangeWasCancelled(grantRequestView));
            pnlStatusChanges.add(wrapSection(inputNew, NewSectionHeader + GrantRequestStatusChangeSubmitted.headerCaption));
            inputNew.display();
            validate();
            pack();
        }
    }
 
    private class ActionListenerCancelGrantRequestButton implements ActionListener {
    
        private GrantRequestView grantRequestView;
        public ActionListenerCancelGrantRequestButton(GrantRequestView grantRequestView) {
            this.grantRequestView=grantRequestView;
        }

        public void actionPerformed(ActionEvent e) {
            grantRequestView.pnlOptionalButtons.setVisible(false);
            
            GrantRequestStatusChangeCancelledView inputNew = GrantRequestStatusChangeCancelled.inputNew(grantRequestView, grantRequest, new ActionListenerNewStatusChangeSaved(grantRequestView), new ActionListenerNewStatusChangeWasCancelled(grantRequestView));
            pnlStatusChanges.add(wrapSection(inputNew, NewSectionHeader + GrantRequestStatusChangeCancelled.headerCaption));
            inputNew.display();
            validate();
            pack();
        }
    }

     
    private class ActionListenerRejectGrantRequestButton implements ActionListener {
    
        private GrantRequestView grantRequestView;
        public ActionListenerRejectGrantRequestButton(GrantRequestView grantRequestView) {
            this.grantRequestView=grantRequestView;
        }

        public void actionPerformed(ActionEvent e) {
            grantRequestView.pnlOptionalButtons.setVisible(false);
            
            GrantRequestStatusChangeRejectedView inputNew = GrantRequestStatusChangeRejected.inputNew(grantRequestView, grantRequest, new ActionListenerNewStatusChangeSaved(grantRequestView), new ActionListenerNewStatusChangeWasCancelled(grantRequestView));
            pnlStatusChanges.add(wrapSection(inputNew, NewSectionHeader + GrantRequestStatusChangeRejected.headerCaption));
            inputNew.display();
            validate();
            pack();
        }
    }

     
    private class ActionListenerAwardGrantRequestButton implements ActionListener {
    
        private GrantRequestView grantRequestView;
        public ActionListenerAwardGrantRequestButton(GrantRequestView grantRequestView) {
            this.grantRequestView=grantRequestView;
        }

        public void actionPerformed(ActionEvent e) {
            grantRequestView.pnlOptionalButtons.setVisible(false);
            
            GrantRequestStatusChangeAwardedView inputNew = GrantRequestStatusChangeAwarded.inputNew(grantRequestView, grantRequest, new ActionListenerNewStatusChangeSaved(grantRequestView), new ActionListenerNewStatusChangeWasCancelled(grantRequestView));
            pnlStatusChanges.add(wrapSection(inputNew, NewSectionHeader + GrantRequestStatusChangeAwarded.headerCaption));
            inputNew.display();
            validate();
            pack();
        }
    }
 
     
    private class ActionListenerCompleteGrantRequestButton implements ActionListener {
    
        private GrantRequestView grantRequestView;
        public ActionListenerCompleteGrantRequestButton(GrantRequestView grantRequestView) {
            this.grantRequestView=grantRequestView;
        }

        public void actionPerformed(ActionEvent e) {
            grantRequestView.pnlOptionalButtons.setVisible(false);
            
            GrantRequestStatusChangeCompletedView inputNew = GrantRequestStatusChangeCompleted.inputNew(grantRequestView, grantRequest, new ActionListenerNewStatusChangeSaved(grantRequestView), new ActionListenerNewStatusChangeWasCancelled(grantRequestView));
            pnlStatusChanges.add(wrapSection(inputNew, NewSectionHeader + GrantRequestStatusChangeCompleted.headerCaption));
            inputNew.display();
            validate();
            pack();
        }
    }

    
    // Erasing the last status change
    private class btnEraseLastStatusChangeActionListener implements ActionListener {
        GrantRequestView parent;
        String sectionTitle;
        GrantRequestStatusChange grantRequestStatusChange;
        private btnEraseLastStatusChangeActionListener(GrantRequestView parent, String sectionTitle, GrantRequestStatusChange grantRequestStatusChange) {
            this.parent=parent;
            this.sectionTitle=sectionTitle;
            this.grantRequestStatusChange=grantRequestStatusChange;
        }

        public void actionPerformed(ActionEvent e) {
            int confirm = JOptionPane.showConfirmDialog(parent, "Are you sure you want to delete this \"" + sectionTitle + "\" status change?\nThis operation is irreversible.", "Confirm Deletion", JOptionPane.OK_CANCEL_OPTION);
            if (confirm==JOptionPane.OK_OPTION) {
                grantRequestStatusChange.delete();
                grantRequest.refreshData();
            }
            // refreshes the display
            parent.initDisplay();
        }
    }

    
    /////////////////////////////////
    // Internal updates listeners
    /////////////////////////////////
    
    // When any status change is actually made
    private class ActionListenerNewStatusChangeSaved implements ActionListener {
    
        private GrantRequestView grantRequestView;
        public ActionListenerNewStatusChangeSaved(GrantRequestView grantRequestView) {
            this.grantRequestView=grantRequestView;
        }

        public void actionPerformed(ActionEvent e) {
            grantRequest=GrantRequest.getById(grantRequest.getId());
            pnlOptionalButtons.setVisible(true);
            // refreshed the display to display the newly created status change
            initDisplay();
        }
    }

    
    // When a status change is deleted 
    private class ActionListenerNewStatusChangeWasCancelled implements ActionListener {
    
        private GrantRequestView grantRequestView;
        public ActionListenerNewStatusChangeWasCancelled(GrantRequestView grantRequestView) {
            this.grantRequestView=grantRequestView;
        }

        public void actionPerformed(ActionEvent e) {
            pnlOptionalButtons.setVisible(true);
            grantRequestView.initDisplay();
        }
    }

}
